package com.digua.base.base

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import androidx.viewbinding.ViewBinding
import com.digua.base.util.CollUtil
import com.digua.base.util.LogUtil
import java.lang.reflect.ParameterizedType

abstract class ListAdapter<UI : ViewBinding, D> : BaseAdapter {
    protected lateinit var ui: UI
    protected var context: Context
    var datas = ArrayList<D>()
        set(value) {
            field.clear()
            field.addAll(value)
            notifyDataSetChanged()
        }

    constructor(context: Context, datas: ArrayList<D> = ArrayList()) : super() {
        this.context = context
        this.datas = datas
    }

    override fun getCount() = CollUtil.size(datas)

    override fun getItem(position: Int) = CollUtil.getVal(datas, position)

    override fun getItemId(position: Int) = position.toLong()

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
        var item = convertView
        if (item == null) {
            try {
                val type = javaClass.genericSuperclass as ParameterizedType
                val cls = type.actualTypeArguments[0] as Class<*>
                val inflate = cls.getDeclaredMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.javaPrimitiveType)
                ui = inflate.invoke(null, LayoutInflater.from(context), parent, false) as UI
                item = ui.root
                item.tag = ui
            } catch (e: Exception) {
                LogUtil.e("异常:", e)
            }
        } else {
            ui = item.tag as UI
        }
        if (item != null) {
            getItem(position)?.let { bindHolder(ui, it, position) }
        }
        return item
    }

    protected abstract fun bindHolder(ui: UI, data: D, position: Int)

    fun addDatas(datas: List<D>?) {
        if (datas.isNullOrEmpty()) return
        this.datas.addAll(datas)
        notifyDataSetChanged()
    }

    fun addData(data: D) {
        datas.add(data)
        notifyDataSetChanged()
    }

    fun addData(index: Int, data: D) {
        datas.add(index, data)
        notifyDataSetChanged()
    }

    fun removeAt(position: Int) {
        datas.removeAt(position)
        notifyDataSetChanged()
    }

}